package com.wsh.redis.redisdemo.config;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.wsh.redis.redisdemo.listener.RedisListener;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author wsh
 * @date 2021/9/14 21:32
 */
@EnableCaching
@Configuration
public class RedisConfig {


    /**
     * redis序列化方式：
     * 1.ByteArrayRedisSerializer
     * Byte数组序列化
     * 2.GenericFastJsonRedisSerializer
     * 同FastJsonRedisSerializer类似
     * <p>
     * 3.FastJsonRedisSerializer
     * 1) 由阿里巴巴FastJson包提供
     * 2) 优点： 1，速度快 2. 兼容性强 3. 占用内存小
     * <p>
     * 4.GenericJackson2JsonRedisSerializer
     * 1) 底层使用Jackson进行序列化并存入Redis。对于普通类型(如数值类型，字符串)可以正常反序列化回相应对象。
     * 2) 存入对象时由于没有存入类信息，则无法反序列化。
     * <p>
     * 5.GenericToStringSerializer
     * 同StringRedisSerializer一样，但它可以将任何对象泛化为字符串并序列化。
     * <p>
     * 6.JdkSerializationRedisSerializer
     * 优点
     * 1) RedisTemplate默认序列化
     * 2) 通用性强
     * 3) 反序列化时不需要提供类型信息(class)
     * 缺点
     * 1) 序列化速度慢
     * 2) 序列化占用内存大
     * 3) 序列化对象必须实现Serializable接口
     * 4) 可读性差(数据存入redis后，如果直接从后台读取数据，可读性不友好)
     * </br>
     * 7.OxmSerializer
     * 1) 以xml格式存储（但还是String类型哦），解析起来也比较复杂。
     * 缺点：
     * 1) 速度慢
     * 2) 占用空间大
     * 8.StringRedisSerializer
     * StringRedisTemplate默认序列化
     * 优点：
     * 1) 可读性强
     * 2) 不需要转换
     * 缺点：
     * 1) 只能对字符串序列化
     * 2) 不能对对象序列化
     * 9.Jackson2JsonRedisSerializer
     * 1) 使用Jackson库将对象序列化为JSON字符串。
     * 优点：
     * 1) 速度快
     * 2) 序列化后的字符串短小精悍
     * 3) 不需要实现Serializable接口
     * 缺点：
     * 必须提供要序列化对象的类型信息(.class对象)
     *
     * @param factory 连接工厂
     * @return RedisTemplate
     */
    @Bean(value = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 对value使用 FastJsonRedisSerializer key使用 StringRedisSerializer
        RedisSerializer<Object> valSerializer = new FastJsonRedisSerializer<>(Object.class);
        RedisSerializer<String> keySerializer = new StringRedisSerializer();

        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(keySerializer);
        redisTemplate.setValueSerializer(valSerializer);
        redisTemplate.setHashKeySerializer(keySerializer);
        redisTemplate.setHashValueSerializer(valSerializer);
        // 初始化redisTemplate
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
        var redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
        return redisMessageListenerContainer;
    }

    @Bean
    public RedisListener redisListener(RedisMessageListenerContainer redisMessageListenerContainer) {
        return new RedisListener(redisMessageListenerContainer);
    }
}
